# -*- coding: utf8 -*-

import urllib2
from puppy.service.Config import PROXYHOST

class SearchEngine(object):
  """
  Generic search engine interface.
  
  SearchEngine configures urllib2 with the PROXYHOST setting, attempts to load the specified search engine, and if unavailable attempts to discover an OpenSearch compliant search engine.
  
  """
  
  def __init__(self, engine):
    """
    Constructor for SearchEngine.
    
    Parameters:
    
    * engine (str): matches a search module from puppy.search.engine, or a URL of an OpenSearch compliant search engine.
    
    TODO might be better described as 'name'
    """
    super(SearchEngine, self).__init__()
    self.engine = engine
    self.configure_opener()
    
  
  def __str__(self):
    return '{0} search engine'.format(self.engine.title())
  
  
  
  def configure_opener(self):
    """Configure urllib2 opener with PROXYHOST."""
    if PROXYHOST != None:
      proxy_support = urllib2.ProxyHandler({'http': PROXYHOST})
      opener = urllib2.build_opener(proxy_support)
    else:
      opener = urllib2.build_opener()
    urllib2.install_opener(opener)
  
  
  def load_engine(self):
    """
    Load specificed search engine, or attempt to discover an OpenSearch compliant service from a URL.
    
    Returns:
      
    * puppy.search.engine module (e.g. Yahoo.py)
    
    """
    try:
      return __import__("puppy.search.engine.{0}".format(self.engine), globals(), locals(), [self.engine], -1)
    except ImportError:
      return __import__("puppy.search.engine.OpenSearch", globals(), locals(), ["OpenSearch"], -1)
  
  
  def search(self, query):
    """
    Perform a search using the specified engine, or OpenSearch compliant service.
    
    Parameters:
    
    * query (puppy.model.OpenSearch.Query): the query object
    
    Returns:
      
    * puppy.model.OpenSearch.Response: the results of the search
    
    Raises:
      
    * Exception: a search engine was not specified
    """
    if self.engine:
      query.service = self.engine
      return self.load_engine().search(query)
    else:
      raise Exception('Search engine not specified')
    


  

